package com.personal.downloadbooks.demos.web.service.impl;


import com.personal.downloadbooks.demos.web.model.DownloadBooks;
import com.personal.downloadbooks.demos.web.properties.DownloadBooksProperties;
import com.personal.downloadbooks.demos.web.service.DownloadBooksService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Service
public class DownloadBooksServiceImpl implements DownloadBooksService {

    private static final String SLASH = "/";

    @Autowired
    private DownloadBooksProperties downloadBooksProperties;

    @Override
    public boolean downloadBooks(DownloadBooks downloadBooks) {
        try {
            // 下载路径(全量路径:下载位置+文件夹名称)
            String mainFileName = downloadBooksProperties.getDownloadPath() + downloadBooks.getMainFileName();
            // 下载链接前缀
            String imageUrlPrefix = downloadBooks.getImageUrl();
//            String imageUrlPrefix = getCutImageUrl(downloadBooks.getImageUrl());
            // 下载文件类型列表
            List<String> pictureType = downloadBooks.getPictureType();
            // 开始页号
            Integer beginPage = downloadBooks.getBeginPage();
            // 开始结束页号
            Integer endPage = downloadBooks.getEndPage();
            // 执行下载
            downloads(mainFileName, imageUrlPrefix, pictureType, beginPage, endPage);
            // TODO 检查完整性
            // 检查完整性
            return checkPageContinuity(mainFileName, beginPage, endPage, pictureType);
        } catch (Exception e) {

        }

        return false;
    }

    private boolean checkPageContinuity(String downloadPath, Integer beginPage, Integer endPage, List<String> pictureTypes) {
        File downloadDir = new File(downloadPath);
        if (!downloadDir.exists() || !downloadDir.isDirectory()) {
            System.out.println("下载目录不存在: " + downloadPath);
            return false;
        }

        // 检查每个页码是否都有对应的文件
        for (int i = beginPage; i <= endPage; i++) {
            boolean pageExists = false;

            // 检查该页码是否存在任何一种图片格式
            for (String pictureType : pictureTypes) {
                File file = new File(downloadPath + "\\" + i + pictureType);
                if (file.exists() && file.length() > 0) {
                    pageExists = true;
                    break;
                }
            }

            // 如果某页没有任何格式的文件，标记为不连续
            if (!pageExists) {
                System.out.println("缺少第 " + i + " 页的图片文件");
                return false;
            }
        }

        System.out.println("页号连续性检查通过: 从第" + beginPage + "页到第" + endPage + "页完整");
        return true;
    }

    public static void downloads(String mainFileName, String imageUrl, List<String> pictureType, Integer beginPage, Integer endPage) throws Exception {
        File file = new File(mainFileName);
        // 如果不存在则创建
        if (!file.exists()) {
            // 全量下载
            file.mkdirs();
            downloadDetail(mainFileName, imageUrl, pictureType, beginPage, endPage);
        } else {
            // 增量下载
            File[] files = file.listFiles();
            if (files != null && files.length > 0) {
                // 过滤出符合图片类型格式的文件
                List<File> imageFiles = Arrays.stream(files)
                        .filter(f -> {
                            String fileName = f.getName().toLowerCase();
                            return pictureType.stream()
                                    .map(String::toLowerCase)
                                    .anyMatch(fileName::endsWith);
                        })
                        .sorted((f1, f2) -> {
                            // 提取文件名中的数字进行排序
                            String name1 = f1.getName();
                            String name2 = f2.getName();
                            // 移除所有可能的图片扩展名
                            for (String type : pictureType) {
                                name1 = name1.replace(type.toLowerCase(), "");
                                name2 = name2.replace(type.toLowerCase(), "");
                            }
                            try {
                                int num1 = Integer.parseInt(name1);
                                int num2 = Integer.parseInt(name2);
                                return Integer.compare(num1, num2);
                            } catch (NumberFormatException e) {
                                return name1.compareTo(name2);
                            }
                        })
                        .collect(Collectors.toList());

                if (!imageFiles.isEmpty()) {
                    // 获取最后一个文件并删除
                    File lastFile = imageFiles.get(imageFiles.size() - 1);
                    boolean deleteSuccess = lastFile.delete();
                    // 无论删除是否成功，都从最后一个文件的序号开始继续下载
                    String lastName = lastFile.getName();
                    // 移除所有可能的图片扩展名获取序号
                    for (String type : pictureType) {
                        lastName = lastName.replace(type.toLowerCase(), "");
                    }
                    int resumePage;
                    try {
                        resumePage = Integer.parseInt(lastName);
                    } catch (NumberFormatException e) {
                        resumePage = beginPage;
                    }
                    downloadDetail(mainFileName, imageUrl, pictureType, resumePage, endPage);
                } else {
                    // 没有找到符合类型的图片文件，从头开始下载
                    downloadDetail(mainFileName, imageUrl, pictureType, beginPage, endPage);
                }
            } else {
                // 文件夹为空，从头开始下载
                downloadDetail(mainFileName, imageUrl, pictureType, beginPage, endPage);
            }
        }
    }


//    private static void downloadDetail(String mainFileName, String imageUrl, List<String> pictureType, Integer beginPage, Integer endPage) throws Exception {
//        System.out.println("=================开始下载=================");
//        // 页数循环
//        for (int i = beginPage; i <= endPage; i++) {
//            Integer pictureTypeCount = 0;
//            // 类型循环
//            // 当前图片类型
//            for (int j = 0; j < pictureType.size(); j++) {
//                pictureTypeCount = j;
//                String currentPictureTypeString = pictureType.get(j);
//                String downloadUrl = imageUrl + i + currentPictureTypeString;
//                try {
//                    downloadWithDeal403(downloadUrl, mainFileName + "\\" + i + currentPictureTypeString);
//                    System.out.println("当前成功下载页数为:" + i + currentPictureTypeString);
//                    // 成功跳出类型循环
//                    break;
//                } catch (Exception e) {
//                    // 如果多种图片类型都获取失败，则程序终止,目前是2，png和jpg
//                    if (Objects.equals(pictureTypeCount, pictureType.size() - 1)) {
//                        throw new Exception("类型为:" + pictureType + ",结束页数为:" + i);
//                    }
//                    // 正常类型未识别就打印一下失败就行
//                    System.out.println("当前失败下载页数为:" + i + currentPictureTypeString + ",失败原因为:" + e);
//                }
//            }
//        }
//        System.out.println("=================结束下载=================");
//    }

    private static void downloadDetail(String mainFileName, String imageUrl, List<String> pictureType, Integer beginPage, Integer endPage) throws Exception {
        System.out.println("=================开始下载: "+imageUrl+"=================");

        // 创建线程池
        int threadCount = Math.min(4, pictureType.size()); // 最多4个线程
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);

        // 页数循环
        for (int i = beginPage; i <= endPage; i++) {
            final int pageNumber = i;

            // 为每一页创建一个任务
            Callable<String> downloadTask = () -> {
                for (int j = 0; j < pictureType.size(); j++) {
                    String currentPictureTypeString = pictureType.get(j);
                    String downloadUrl = imageUrl + pageNumber + currentPictureTypeString;
                    String destinationFile = mainFileName + "\\" + pageNumber + currentPictureTypeString;

                    try {
                        downloadWithDeal403(downloadUrl, destinationFile);
                        System.out.println("当前成功下载页数为:" + pageNumber + currentPictureTypeString);
                        // 成功后返回成功信息
                        return "SUCCESS:" + pageNumber + currentPictureTypeString;
                    } catch (Exception e) {
                        // 如果是最后一种类型还失败了，记录错误
                        if (j == pictureType.size() - 1) {
                            System.out.println("当前失败下载页数为:" + pageNumber + currentPictureTypeString + ",失败原因为:" + e);
                            return "FAILED:" + pageNumber + currentPictureTypeString;
                        } else {
                            // 继续尝试下一种类型
                            System.out.println("尝试下载页数" + pageNumber + "失败，尝试其他格式:" + currentPictureTypeString + ",失败原因为:" + e);
                        }
                    }
                }
                return "FAILED:" + pageNumber;
            };

            // 提交任务并等待完成
            try {
                Future<String> future = executor.submit(downloadTask);
                future.get(); // 等待当前页下载完成后再下载下一页
            } catch (Exception e) {
                System.out.println("下载第" + pageNumber + "页时发生异常: " + e.getMessage());
            }
        }

        // 关闭线程池
        executor.shutdown();

        System.out.println("=================结束下载 "+imageUrl+"=================");
    }

    public static void downloadWithDeal403(String imageUrl, String destinationFile) throws IOException {
        // 设置代理服务器信息
        String proxyHost = "127.0.0.1";
        int proxyPort = 10809;
        String proxyUser = null; // 如果代理服务器需要验证
        String proxyPassword = null; // 如果代理服务器需要验证
        try {
            URL url = new URL(imageUrl);
            // 创建代理服务器对象
            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
            // 打开连接时指定代理
            URLConnection conn = url.openConnection(proxy);
            // 如果代理服务器需要验证，则设置认证信息
            if (proxyUser != null && proxyPassword != null) {
                String auth = proxyUser + ":" + proxyPassword;
                String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
                conn.setRequestProperty("Proxy-Authorization", "Basic " + encodedAuth);
            }
            conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
            InputStream inputStream = conn.getInputStream();
            OutputStream outputStream = new FileOutputStream(destinationFile);
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.close();
            inputStream.close();
        } catch (IOException e) {
//            e.printStackTrace();
            throw e;
        }
    }

//    private static String getCutImageUrl(String imageUrl) {
//        int lastPart = imageUrl.lastIndexOf(SLASH);
//        return imageUrl.substring(0, lastPart + 1);
//    }

}